<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 Input-Output
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora026.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora028.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> Input-Output</H2>
<A NAME="sec-PI-IO"></A>
<A NAME="@fonctions106"></A>
<A NAME="@fonctions107"></A>
<A NAME="@fonctions108"></A>
<A NAME="@fonctions109"></A>
<A NAME="@fonctions110"></A>
<A NAME="@fonctions111"></A>
Input-output functions do calculate a value (often of type
<I>unit</I>) but during their calculation they cause a modification
of the state of the input-output peripherals: modification of the
state of the keyboard buffer, outputting to the screen,
writing in a file, or modification of a read pointer. The following two
types are predefined: <I>in_channel</I> and <I>out_channel</I>
for, respectively, input channels and output channels. When an end of
file is met, the exception <TT>End_of_file</TT> is raised. Finally,
the following three constants correspond to the standard channels for
input, output, and error in Unix fashion: <TT>stdin</TT>,
<TT>stdout</TT>, and <TT>stderr</TT>.<BR>
<BR>
<A NAME="toc36"></A>
<H3> Channels</H3>
<A NAME="@concepts106"></A>
The input-output functions from the Objective CAML standard library
manipulate communication channels: values of type
<I>in_channel</I> or <I>out_channel</I>. Apart from the three
standard predefined values, the creation of a channel uses one of the
following functions:
<A NAME="@fonctions112"></A>
<A NAME="@fonctions113"></A>


<PRE><BR># open_in;;<BR><CODE>- : string -&gt; in_channel = &lt;fun&gt;</CODE><BR># open_out;;<BR><CODE>- : string -&gt; out_channel = &lt;fun&gt;</CODE><BR>

</PRE>

<A NAME="@fonctions114"></A>
<TT>open_in</TT> opens the file if it exists<A NAME="text13" HREF="book-ora034.html#note13"><SUP><FONT SIZE=2>2</FONT></SUP></A>, and otherwise raises the exception
<TT>Sys_error</TT>. 
<TT>open_out</TT> creates the specified file if it does not exist or
truncates it if it does.


<PRE><BR># <B>let</B><CODE> </CODE>ic<CODE> </CODE><CODE>=</CODE><CODE> </CODE>open_in<CODE> </CODE><CODE>"koala"</CODE>;;<BR><CODE>val ic : in_channel = &lt;abstr&gt;</CODE><BR># <B>let</B><CODE> </CODE>oc<CODE> </CODE><CODE>=</CODE><CODE> </CODE>open_out<CODE> </CODE><CODE>"koala"</CODE>;;<BR><CODE>val oc : out_channel = &lt;abstr&gt;</CODE><BR>

</PRE>

<A NAME="@fonctions115"></A>
<A NAME="@fonctions116"></A>
The functions for closing channels are:


<PRE><BR># close_in<CODE> </CODE>;;<BR><CODE>- : in_channel -&gt; unit = &lt;fun&gt;</CODE><BR># close_out<CODE> </CODE>;;<BR><CODE>- : out_channel -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
<A NAME="toc37"></A>
<H3> Reading and Writing</H3>
The most general functions for reading and writing are the following:
<A NAME="@fonctions117"></A>
<A NAME="@fonctions118"></A>
<A NAME="@fonctions119"></A>


<PRE><BR># input_line<CODE> </CODE>;;<BR><CODE>- : in_channel -&gt; string = &lt;fun&gt;</CODE><BR># input<CODE> </CODE>;;<BR><CODE>- : in_channel -&gt; string -&gt; int -&gt; int -&gt; int = &lt;fun&gt;</CODE><BR># output<CODE> </CODE>;;<BR><CODE>- : out_channel -&gt; string -&gt; int -&gt; int -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
<UL>
<LI>
 input_line<CODE> </CODE>ic: reads from input channel <TT>ic</TT>
all the characters up to the first carriage return or end of file, and
returns them in the form of a list of characters (excluding the
carriage return).

<LI> input<CODE> </CODE>ic<CODE> </CODE>s<CODE> </CODE>p<CODE> </CODE>l: attempts to read <TT>l</TT>
characters from an input channel <TT>ic</TT> and stores them in the
list <TT>s</TT> starting from the <TT>p</TT><SUP><FONT SIZE=2><I>th</I></FONT></SUP>
character. The number of characters actually read is returned.

<LI> output<CODE> </CODE>oc<CODE> </CODE>s<CODE> </CODE>p<CODE> </CODE>l: writes on an output channel
<TT>oc</TT> part of the list <TT>s</TT>, starting at the <TT>p</TT>-th
character, with length <TT>l</TT>.
</UL>The following functions read from standard input or write to standard
output: 
<A NAME="@fonctions120"></A>
<A NAME="@fonctions121"></A>
<A NAME="@fonctions122"></A>


<PRE><BR># read_line<CODE> </CODE>;;<BR><CODE>- : unit -&gt; string = &lt;fun&gt;</CODE><BR># print_string<CODE> </CODE>;;<BR><CODE>- : string -&gt; unit = &lt;fun&gt;</CODE><BR># print_newline<CODE> </CODE>;;<BR><CODE>- : unit -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
Other values of simple types can also be read directly or
appended. These are the values of types which can be converted into
lists of characters.<BR>
<BR>

<H5> Local declarations and order of evaluation</H5>
We can simulate a sequence of printouts with expressions
of the form <EM>let x = e</EM><SUB><EM><FONT SIZE=2>1</FONT></EM></SUB><EM> in e</EM><SUB><EM><FONT SIZE=2>2</FONT></EM></SUB>. Knowing that, in general, 
<TT>x</TT> is a local variable which can be used in <EM>e</EM><SUB><EM><FONT SIZE=2>2</FONT></EM></SUB>, we
know that <EM>e</EM><SUB><EM><FONT SIZE=2>1</FONT></EM></SUB> is evaluated first and then comes the turn of
<EM>e</EM><SUB><EM><FONT SIZE=2>2</FONT></EM></SUB>. If the two expressions are imperative functions
whose results are <EM>()</EM> but which have side effects, then we
have executed them in the right order. In particular, since we know
the return value of <EM>e</EM><SUB><EM><FONT SIZE=2>1</FONT></EM></SUB>---the constant () of
type <I>unit</I>---we get a sequence of printouts by writing the
sequence of nested declarations which pattern match on ().<BR>
<BR>


<PRE><BR># <B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"and one,"</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>" and two,"</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>" and three"</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>" zero"</CODE>;;<BR><CODE>and one, and two, and three zero- : unit = ()</CODE><BR>

</PRE>
<BR>
<BR>
<A NAME="toc38"></A>
<H3> Example: Higher/Lower</H3><A NAME="cpcm"></A>
The following example concerns the game ``Higher/Lower''
which consists of choosing a number which the user must
guess at. The program indicates at each turn whether the chosen number is
smaller or bigger than the proposed number.<BR>
<BR>


<PRE><BR># <CODE> </CODE><B>let</B><CODE> </CODE><B>rec</B><CODE> </CODE>hilo<CODE> </CODE>n<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"type a number: "</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>read_int<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>n<CODE> </CODE><B>then</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"BRAVO"</CODE><CODE> </CODE><B>in</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_newline<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>print_newline<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>i<CODE> </CODE><CODE>&lt;</CODE><CODE> </CODE>n<CODE> </CODE><B>then</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"Higher"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>print_newline<CODE> </CODE>()<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>print_string<CODE> </CODE><CODE>"Lower"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>print_newline<CODE> </CODE>()<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>in</B><CODE> </CODE>hilo<CODE> </CODE>n<CODE> </CODE>;;<BR><CODE>val hilo : int -&gt; unit = &lt;fun&gt;</CODE><BR>

</PRE>
<BR>
<BR>
Here is an example session:
<PRE>
# hilo 64;;
type a number: 88
Lower
type a number: 44
Higher
type a number: 64
BRAVO

- : unit = ()
</PRE><HR>
<A HREF="book-ora026.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora028.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
